package com.fit.utils.se;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.*;

/**
 * 序列化工具类
 * 需要被序列化的对象必须实现Serializable接口或者Externalizable接口
 * 在需要序列化的bean对象中 重写serialVersionUID版本号后,反序列化时,
 * 就算序列化的类发生了变化,也能反序列化成功(也就表示序列化时到反序列化时,
 * 被序列化的类中的serialVersionUID不能发生变化)
 * @author hcl
 *
 */
public class SerializableUtil {
	
	private static Logger log = LoggerFactory.getLogger(SerializableUtil.class);
	
	/**
	 * 序列化方法
	 * @param obj 被序列化的对象
	 * @param out 输出流
	 */
    public static void serializable(Serializable obj,OutputStream out){
        try {
			ObjectOutputStream outputStream = new ObjectOutputStream(out);
	        outputStream.writeObject(obj);
		} catch (IOException e) {
			log.error("序列化异常！", e);
			throw new RuntimeException("序列化异常！", e);
		}finally{
			IOUtil.close(out);
		}
    }
    
    /**
     * 序列化成一个文件
     * @param obj 被序列化的对象
     * @param file 文件对象
     */
    public static void serializable(Serializable obj,File file){
    	try {
			serializable(obj, new FileOutputStream(file));
		} catch (FileNotFoundException e) {
			log.error("序列化异常！没有找到对应的文件。", e);
		}
    }
    
    /**
     * 序列化成一个文件
     * @param obj 被序列化的对象
     * @param filePath 绝对路径(如果路径没有这个文件,就重新创建一个文件)
     */
    public static void serializable(Serializable obj,String filePath){
		File file = new File(filePath);
		if(!file.exists()){
			try {
				file.createNewFile();
			} catch (IOException e) {
				log.error("序列化异常！创建文件失败。", e);
				throw new RuntimeException("序列化异常！创建文件失败。", e);
			}
		}
		serializable(obj, file);
    }
    
    /**
     * 序列化成一个byte数组
     * @param obj 被序列化的对象
     * @return byte数组
     */
    public static byte[]  serializable(Serializable obj){
    	ByteArrayOutputStream out = new ByteArrayOutputStream();
    	serializable(obj, out);
    	return out.toByteArray();
    }
    
    /**
     * 将一个流反序列化为一个对象
     * @param in 输入流
     * @return
     */
    @SuppressWarnings("unchecked")
	public static <T> T deSerializable(InputStream in){
    	T result = null;
    	try{
    		ObjectInputStream ois = new ObjectInputStream(in);
    		result = (T)ois.readObject();
    	} catch (Exception e) {
			log.error("反序列化异常!", e);
			throw new RuntimeException("反序列化异常!", e);
		} finally{
			IOUtil.close(in);
		}
    	return result;
    }
    
    /**
     * 将一个文件反序列化为一个对象
     * @param file 文件
     * @return
     */
    public static <T> T deSerializable(File file){
    	T result = null;
    	try {
    		result = deSerializable(new FileInputStream(file));
		} catch (FileNotFoundException e) {
			log.error("反序列化异常！目标文件不存在", e);
			throw new RuntimeException("反序列化异常！目标文件不存在", e);
		}
    	return result;
    }
    
    
    /**
     * 将一个文件反序列化为一个对象
     * @param filePath 文件路径(绝对路径)
     * @return
     */
    public static <T> T deSerializable(String filePath){
    	return deSerializable(new File(filePath));
    }
    
    
    /**
     * 将一个byte数组反序列化为一个对象
     * @param b 需要被反序列化的byte数组
     * @return
     */
    public static <T> T deSerializable(byte[] b){
    	return deSerializable(new ByteArrayInputStream(b));
    }
}
